#!/usr/bin/python
# -*- coding: utf-8 -*-

import sys
import os
import json
import commands


# 生成packages目录
def make_packages_dir(root_path):
    packages_dir = root_path+'/packages'
    if not os.path.exists(packages_dir):
        print('create packages dir,' + packages_dir)
        os.mkdir(packages_dir)

# git clone 依赖的工程
def get_dep_project(root_path, dep):
    make_packages_dir(root_path)
    packages_dir = root_path+'/packages'
    pro_dir = packages_dir + '/' + dep['name'] + '_' + dep['version']
    if os.path.exists(pro_dir):
        return True
    
    cmd = 'cd %s; git clone %s -b %s %s' % (packages_dir, dep['url'], dep['version'], pro_dir)
    print('git clone project %s...' % (dep['name'],))
    #ret = commands.getstatusoutput(cmd)
    ret = os.system(cmd)
    if ret != 0:
        print('cmd:%s exec failed.', (cmd,))
        return False
    return True
	
# 依赖库列表转字符串, 根据层次解决依赖顺序
def get_libs_str(dic):
    list = sorted(dic.iteritems(), key = lambda asd:asd[1], reverse = False)
    str = ' '
    for k,v in list:
        str += k
        str += ' '
    return str
	
# 字典合并
def combie_dic(d1, d2):
    dic = {}
    for k, v in d1.items():
        dic[k] = v
    for k, v in d2.items():
        if dic.has_key(k):
            if v > dic[k]:
                dic[k] = v
        else:
            dic[k] = v
    return dic

# 这个要支持递归生成所有依赖的CMake配置
# param pro_path 工程的project.json目录路径
# param root_path 本次主工程Root路径
# param deep 递归层次
# return 返回(结果, 所有依赖的工程的库目标, 所有依赖的系统库目标)
def parse_cmake(pro_path, root_path, deep):
    fin = open(pro_path + '/package.json', 'r')
    pro = json.load(fin)
    str = "cmake_minimum_required(VERSION 2.8)\n"
    str += "project(%s)\n\n" % (pro["project"],)
    #print('project(%s) begin parseing' % (pro["project"]))
    str += 'set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} %s")\n\n' %  (" ".join(pro["tags"]),)
    #str += 'file (GLOB source\n\t\t"sources/*.cpp"\n)\n\n'
	
    dep_libs = {}
    dep_sys_libs = {}
    dep_sys_links = []

    # 系统依赖处理
    str += 'include_directories(sources)\n'
    sys_dep_data = pro['sys_deps']
    for sys_dep in sys_dep_data:
        if sys_dep['include'] != None and sys_dep['include'] != '':
            str += 'include_directories(%s)\n' % (sys_dep['include'],)
        if sys_dep['linkpath'] != None and sys_dep['linkpath'] != '':
            #str += 'link_directories(%s)\n' % (sys_dep['linkpath'],)
            dep_sys_links.append(sys_dep['linkpath'])
        if sys_dep['lib'] != None and sys_dep['lib'] != '':
            dep_sys_libs[sys_dep['lib']] = deep
    #for sys_inc in sys_dep_data['include']:
        #str += 'include_directories(%s)\n' % (sys_inc,)
    #for syslib in sys_dep_data['libs']:
        #dep_sys_libs[syslib] = deep
	
    # 依赖库处理
    if len(pro['deps']) > 0:
        str += 'if(NOT DEFINED PROJECT_ROOT)\n'		
        str += 'set(PROJECT_ROOT ${PROJECT_SOURCE_DIR})\n'
    for dep in pro['deps']:
        ret = get_dep_project(root_path, dep)
        if ret != True:
            return False
        # 生成所有依赖工程的CMake配置
        dep_pro_dir = root_path + '/packages' + '/' + dep['name'] + '_' + dep['version']
        ret, libs, syslibs, syslinks = parse_cmake(dep_pro_dir, root_path, deep+1)
        if ret != True:
            return False
        dep_libs = combie_dic(dep_libs, libs)
        dep_sys_libs = combie_dic(dep_sys_libs, syslibs)
        dep_sys_links = dep_sys_links + syslinks
        str += '\tinclude_directories(${PROJECT_ROOT}/packages/%s/sources)\n' % (dep['name'] + '_' + dep['version'],)
        str += '\tadd_subdirectory(packages/%s)\n' % (dep['name'] + '_' + dep['version'],)
    if len(pro['deps']) > 0:
		str += 'endif()\n\n'
		
    # 系统库路径处理
    for link in dep_sys_links:
        str += 'link_directories(%s)\n' % (link,)
    #str += '\n\n'
	
    for target in pro["targets"]:
        str += 'file (GLOB %s_source\n\t%s)\n' % (target['name'], target['file'])
        if target['type'] == 'lib':
            str += 'add_library(%s ${%s_source})\n' % (target['name'], target['name'])
            dep_libs[target['name']] = deep
        elif target['type'] == 'exec':
            str += 'add_executable(%s ${%s_source})\n' % (target['name'], target['name'])
            str += 'target_link_libraries(%s %s)\n' % (target['name'], get_libs_str(dep_libs) + get_libs_str(dep_sys_libs))
        str += '\n'

	# 安装项, 安装路径为
    #str += '\n\n'
    if pro.has_key('installs'):
        str += 'SET (CMAKE_INSTALL_PREFIX ${PROJECT_SOURCE_DIR})\n'
        for install in pro['installs']:
            if install['type'] == 'file':
                str += 'install(FILES ' + install['target'] + ' DESTINATION ' + install['destination'] + ')\n'
            elif install['type'] == 'exec':
                str += 'install(TARGETS ' + install['target'] + ' RUNTIME DESTINATION ' + install['destination'] + ')\n'
   
    f = open(pro_path + '/' + 'CMakeLists.txt', 'w')	
    f.write(str)
    f.close()
    print('project(%s) parsed ok' % (pro['project'],))
    return True, dep_libs, dep_sys_libs, dep_sys_links

if __name__ == '__main__':
    pro_root_path = os.getcwd()
    print('project root:%s' % (pro_root_path,))
    parse_cmake(pro_root_path, pro_root_path, 0)
